package ru.nsu.fit.iconveyor.conveyor.storage.exporter;

import ru.nsu.fit.iconveyor.conveyor.Conveyor;
import ru.nsu.fit.iconveyor.conveyor.Globals;
import ru.nsu.fit.iconveyor.conveyor.storage.exporter.graphml.GraphMLExporter;
import ru.nsu.fit.iconveyor.conveyor.node.Node;
import ru.nsu.fit.iconveyor.conveyor.utils.file.CopyFile;
import ru.nsu.fit.iconveyor.conveyor.utils.zip.Zip;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.net.URL;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * This class make export to icon file from class conveyor.
 *
 * @author Timur Zolotuhin (tzolotuhin@gmail.com)
 */
public class Exporter {
    /**
     * Exports conveyor to file with fileName.
     * Node 1: don't find dependencies classes of node executors.
     * Note 2: .class file may be removed.
     */
    @Deprecated
    public static void exportToFile(String fileName, Conveyor conveyor) throws Exception {
        // create temp directory
        File myTempDir = File.createTempFile("install", "dir");
        myTempDir.delete();
        if (myTempDir.mkdirs() == false)
            throw new FileNotFoundException("Can't create temporary directory = " + myTempDir.getAbsolutePath());

        // collect resources
        Collection<Node> nodes = conveyor.getNodes();
        Map<Class<?>, URL> urls = new HashMap<Class<?>, URL>();
        for (Node node: nodes) {
            URL url = getClassLocation(node.getClass());
            if (url == null) {
                throw new Exception("Couldn't find executor class URL = " + url.toString());
            }
            urls.put(node.getClass(), url);
        }

        // save graphml file
        GraphMLExporter.saveGraphML(myTempDir.getAbsolutePath() + File.separator + Globals.GRAPHML_FILE_NAME_IN_ARCHIVE, conveyor);

        // save properties
        FileOutputStream out = null;
        try {
            Properties prop = conveyor.getProperties();
            out = new FileOutputStream(myTempDir.getAbsolutePath() + File.separator + Globals.PROPERTIES_FILE_NAME_IN_ARCHIVE);
            prop.store(out, "");
        } catch (Exception ex) {

        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (Exception ex) {}
            }
        }

        // save jar file
        File jarTempDir = File.createTempFile("install", "dir");
        jarTempDir.delete();
        if (jarTempDir.mkdir() == false)
            throw new FileNotFoundException("Can't create temporary folder = " + jarTempDir.getAbsolutePath());
        for (Class<?> clazz : urls.keySet()) {
            URL url = urls.get(clazz);
            String packageName = "";
            if (clazz.getPackage() != null)
                packageName = clazz.getPackage().getName();
            packageName = packageName.replace(".", File.separator.toString());
            CopyFile.copyFile2Directory(url, clazz.getSimpleName() + ".class", jarTempDir.getAbsolutePath() + File.separator + packageName);
        }
        Zip.zipWithoutRootFolder(myTempDir.getAbsolutePath() + File.separator + Globals.JAR_FILE_NAME_IN_ARCHIVE, jarTempDir.getAbsolutePath());


        // zip this directory
        Zip.zip(fileName, myTempDir.getAbsolutePath());
    }

    public static void exportToFile(String fileName, Conveyor conveyor, String jarFileName) throws Exception {
        // create temp directory
        File myTempDir = File.createTempFile("install", "dir");
        myTempDir.delete();
        if (myTempDir.mkdirs() == false)
            throw new FileNotFoundException("Can't create temporary directory = " + myTempDir.getAbsolutePath());

        // collect resources
        Collection<Node> nodes = conveyor.getNodes();

        // save graphml file
        GraphMLExporter.saveGraphML(myTempDir.getAbsolutePath() + File.separator + Globals.GRAPHML_FILE_NAME_IN_ARCHIVE, conveyor);

        // save jar file
        CopyFile.copyFile(jarFileName, myTempDir.getAbsolutePath() + File.separator + Globals.JAR_FILE_NAME_IN_ARCHIVE);

        // save properties
        FileOutputStream out = null;
        try {
            Properties prop = conveyor.getProperties();
            out = new FileOutputStream(myTempDir.getAbsolutePath() + File.separator + Globals.PROPERTIES_FILE_NAME_IN_ARCHIVE);
            prop.store(out, "");
        } catch (Exception ex) {

        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (Exception ex) {}
            }
        }

        // zip this directory
        Zip.zip(fileName, myTempDir.getAbsolutePath());
    }

    private static URL getClassLocation(final Class<?> pClass) {
        final String location, name;
        name = pClass.getName().replaceAll("\\.", "/") + ".class";
        return pClass.getClassLoader().getResource(name);
    }
}
